//
//  BoundViewModel.swift
//  Alamofire
//
//  Created by 李然 on 2024/4/27.
//

import Foundation
@_exported import EarbudsCommon
@_exported import MoyoungLib
@_exported import RxSwift
@_exported import RxCocoa
@_exported import XCGLogger

public enum BoundConnectStatus {
    case connecting
    case connected
    case connectFailed
}

public class BoundViewModel: ViewModel, ViewModelType {
    
    public struct Input {
        public let reScan: Observable<Void>
        public init(reScan: Observable<Void>) {
            self.reScan = reScan
        }
    }
    
    public struct Output {
        public let dataSource: Observable<[BoundDeviceViewModel]>
        public let isSeaching: Observable<Bool>
        public let connectStatus: Driver<BoundConnectStatus>
    }
    
    public func transform(input: Input) -> Output {
        
        let dataSource = BehaviorRelay<[BoundDeviceViewModel]>(value: [])
        let isSeaching = BehaviorRelay<Bool>(value: false)
        
        Observable.of(input.reScan, Observable.just(()))
            .merge()
            .subscribe(onNext: { [weak self] _ in
                guard let `self` = self else { return }
                
                isSeaching.accept(true)
                dataSource.accept([])
                
                BluetoothManager.shared.scan().debug("蓝牙请求")
                    .subscribe(onNext: { discoverys in
                        dataSource.accept(discoverys.map{ BoundDeviceViewModel(device: Device(discovery: $0)) })
                    }, onError: { _ in
                        isSeaching.accept(false)
                    }, onCompleted: {
                        isSeaching.accept(false)
                    }).disposed(by: self.rx.disposeBag)
                
            }).disposed(by: rx.disposeBag)
        
        /// 开始连接后 20 秒超时事件
        let timeOut = BluetoothManager.shared.connectState
            .filter{ $0 == .connecting || $0 == .connected }
            .flatMapLatest { _ in
                return Observable<Int>.timer(.seconds(20), scheduler: MainScheduler.instance)
            }
            .map{ _ in return BoundConnectStatus.connectFailed }
        
        let bleStatus = BluetoothManager.shared.connectState
            .filter{ $0 == .connected || $0 == .connecting || $0 == .syncing }
            .map { statue -> BoundConnectStatus in
                switch statue {
                case .connected, .syncing: 
                    return .connected
                default:
                    return .connecting
                }
            }
        
        let bindStatus = Observable.of(timeOut, bleStatus).merge()
        
        return Output(dataSource: dataSource.asObservable(),
                      isSeaching: isSeaching.asObservable(),
                      connectStatus: bindStatus.asDriverOnErrorJustComplete())
    }
}
